package pers.llc.css.nio.demo;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

/**
 * @author fancy
 * @time 2019/3/31 0031 13:54
 */
public class SocketChannelServer {
    public static Selector selector = null;



    public static void init() {
        initSelector();
        initServerSocketChannel();
        run();
    }

    // first
    public static void initSelector() {
        try {
            selector = Selector.open();
        } catch (IOException e) {
        }
    }

    public static void initServerSocketChannel() {
        try {
            ServerSocketChannel server = ServerSocketChannel.open();
            server.socket().bind(new InetSocketAddress(7777), 1024);
            server.configureBlocking(false);
            server.register(selector, SelectionKey.OP_ACCEPT);
        } catch (IOException e) {
            // 初始化serverSocket失败
            e.printStackTrace();
        }
    }

    public static void run() {
        while (true) {
            try {
                selector.select(1000);
                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectedKeys.iterator();
                SelectionKey key;
                while (iterator.hasNext()) {
                    key = iterator.next();
                    handle(key);
                    iterator.remove();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void handle(SelectionKey key) {
        try {
            // 连接就绪
            if (key.isAcceptable()) {
                handleAcceptable(key);
            }
            // 读就绪
            if (key.isReadable()) {
                handelReadable(key);
            }
        } catch (IOException e) {
            key.cancel();
            if (key.channel() != null) {
                try {
                    key.channel().close();
                } catch (IOException e1) {
                }
            }
        }
    }


    public static void handelReadable(SelectionKey key) throws IOException {

        SocketChannel ssc = (SocketChannel) key.channel();
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        String content = "接收到客户端信息: ";
        int readBytes = ssc.read(byteBuffer);
        if (readBytes > 0) {
            byteBuffer.flip();
            byte[] bytes = new byte[byteBuffer.remaining()];
            byteBuffer.get(bytes);
            content += new String(bytes);
            System.out.println(content);
        }
    }

    public static void handleAcceptable(SelectionKey key) throws IOException {

        ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
        SocketChannel channel = ssc.accept();
        channel.configureBlocking(false);
        channel.register(selector, SelectionKey.OP_READ);
        // 将key对应Channel设置为准备接受其他请求
        key.interestOps(SelectionKey.OP_ACCEPT);

        new Thread(() -> {
            try {
                while (true) {
                    Thread.sleep(2000);
                    input(channel);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

    }

    public static void input(SocketChannel channel) throws IOException {
        ReadableByteChannel source = Channels.newChannel(System.in);
        ByteBuffer bytebuffer = ByteBuffer.allocateDirect(1024);
        while (source.read(bytebuffer) != -1) {
            bytebuffer.flip();
            while (bytebuffer.hasRemaining()) {
                channel.write(bytebuffer);
            }
            bytebuffer.clear();
            System.out.println("服务端发送信息完成");
        }
    }

    public static void main(String[] args) {
        SocketChannelServer.init();
    }
}
